home *** CD-ROM | disk | FTP | other *** search
- /* check_port.c */
-
- /* Copyright © 1989 by Donald T. Meyer, Stormgate Software
- * All Rights Reserved
- */
-
- /*
- * Revised:
- * Andrew C. R. Martin 11.12.91 23:30
- * SciTech Software
- *
- * The AllocMem(strlen(ARG0(...)),0L) seemed to be expanding the
- * ARG0() macro incorrectly causing 2 too few bytes to be allocated.
- * Hence MungWall hits!
- * Now uses an intermediate variable.
- * Changes are bracketed by ACRM+ and ACRM-
- */
-
-
-
- #include "rxil.h"
-
- #include <string.h>
-
-
-
- static void handle_message( struct RexxMsg *rexxmsg );
- static void handle_rexx_message( struct RexxMsg *rexxmsg );
- static void handle_return( struct RxilInvocation *rxi );
-
- static int parse_inplace( char *p, char **argptr, int maxargs );
-
-
-
- /*------------------------------------------------------------------*/
- /* Functions */
- /*------------------------------------------------------------------*/
-
- /* NAME
- * RxilCheckPort
- *
- * SYNOPSIS
- * RxilCheckPort();
- *
- * FUNCTION
- * Called by the client program's eventloop upon recieving a message
- * at one of the ports.
- * This handles the dispatching ( via RxilDispatch() ) of ARexx
- * commands, the launching of "looped back" macros, and receiving
- * the replys to macro invocation messages which we have sent to
- * Rexxmaster.
- *
- * This is a "safe" call in that if the ARexx library was unopened
- * or the port opening failed, nothing will go boom!
- *
- * INPUTS
- * None
- *
- * RESULT
- * None
- *
- * SIDES
- *
- * HISTORY
- * 01-Aug-89 Creation.
- * 18-Nov-89 Changed an (incorrect) error return code in line 212.
- *
- * BUGS
- *
- * SEE ALSO
- * RxilInit(), RxilDispatch()
- */
-
- void RxilCheckPort( void )
- {
- struct RexxMsg *rexxmsg;
-
-
- /* Make call "safe" even if RxilInit() failed */
- if( global_rdef == NULL )
- {
- return;
- }
-
-
- if( RxilCheckCancel() == TRUE )
- {
- /* It would appear that a cancel requester was posted, and
- * the user clicked it!
- */
- RxilCancel();
- }
-
-
- if( global_rdef->SecretPort )
- {
- while( rexxmsg = (struct RexxMsg *)
- GetMsg( global_rdef->SecretPort ) )
- {
- global_rdef->FromRexx = RXIL_SECRET;
- handle_message( rexxmsg );
- global_rdef->FromRexx = 0;
- }
- }
-
- if( global_rdef->PublicPort )
- {
- while( rexxmsg = (struct RexxMsg *)
- GetMsg( global_rdef->PublicPort ) )
- {
- global_rdef->FromRexx = RXIL_PUBLIC;
- handle_message( rexxmsg );
- global_rdef->FromRexx = 0;
- }
- }
-
-
- /* Do we want to clear the Abort flag? */
-
- if( RxilPending() == FALSE )
- {
- if( global_rdef->CReq != NULL )
- {
- RxilEndCancel();
- }
-
- if( FlagIsClear( global_rdef->Flags, RXIL_NO_CLEARABORT ) )
- {
- global_rdef->Abort = FALSE;
- }
- }
- }
-
-
-
- /* This routine is called with the message received at any rexx port.
- * These messages will be of two broad classes.
- * The first is a reply from a command or function which we invoked
- * by sending a packet to RexxMaster.
- *
- * The second is a command sent to our application by an ARexx
- * program. This could potentialy be from the public port or from
- * the uniquely-named private port.
- */
-
- static void handle_message( struct RexxMsg *rexxmsg )
- {
- struct RxilInvocation *rxi;
-
-
- /* Decide if it is a reply */
-
- for( rxi=global_rdef->Invocations; rxi; rxi=rxi->Next )
- {
- /* Is this an invocation reply? */
- if( rexxmsg == rxi->RexxMsg )
- {
- /* Yes */
- handle_return( rxi );
- return;
- }
- }
-
-
- /* Apparently not a completion message. Should be a command
- * from a Rexx program.
- */
-
- if( IsRexxMsg(rexxmsg) == FALSE )
- {
- /* This message is not from ARexx. Don't touch it,
- * just Reply() it and return.
- */
- ReplyMsg( (struct Message *)rexxmsg );
- return;
- }
-
-
- /* The message is from an ARexx program */
-
- handle_rexx_message( rexxmsg );
- }
-
-
-
- /* This will take a command message received from an ARexx program
- * and handle the dispatching and replying.
- * This message MUST be from an ARexx program!
- */
-
- static void handle_rexx_message( struct RexxMsg *rexxmsg )
- {
- char *cmdbuf;
- struct RxilInvocation *child_rxi;
-
- /* ACRM+ */
- long memsize;
- /* ACRM- */
-
- /* Default to okay code. */
- rexxmsg->rm_Result1 = RC_OK;
- rexxmsg->rm_Result2 = 0;
-
-
- /* Are we still open for business? */
- if( global_rdef->Abort == TRUE )
- {
- /* Nope! */
- rexxmsg->rm_Result1 = RXERR_ABORTED;
- ReplyMsg( (struct Message *)rexxmsg );
- return;
- }
-
-
- /* Handle the message contents */
-
- /* Just to be squeaky clean, since Bill says to affect only the
- * result fields, copy this into a buffer before parsing.
- *
- * NOTE: Even though an Argstring can by definition contain
- * embedded null's, the command line is treated as though it
- * were null terminated.
- */
-
- /* ACRM+
- // cmdbuf = AllocMem( strlen( ARG0(rexxmsg) )+1, 0 );
- */
- memsize = strlen(rexxmsg->rm_Args[0])+1;
- cmdbuf = AllocMem( memsize, 0L );
- /* ACRM- */
-
- if( cmdbuf == NULL )
- {
- rexxmsg->rm_Result1 = RXERR_NO_MEMORY;
- return;
- }
-
- strcpy( cmdbuf, ARG0(rexxmsg) );
-
- /* Parse the command string */
- global_rdef->ArgCount =
- parse_inplace( cmdbuf, &(global_rdef->Arg[0]), RXIL_MAX_ARGS );
-
- if( global_rdef->ArgCount == 0 )
- {
- rexxmsg->rm_Result1 = RXERR_UNKNOWN_CMD;
-
- /* ACRM+
- // FreeMem( cmdbuf, strlen( ARG0(rexxmsg) ) );
- */
- FreeMem( (void *)cmdbuf, memsize );
- /* ACRM- */
-
- return;
- }
-
- RxilDispatch( rexxmsg, global_rdef->Arg[0] );
-
- /* ACRM+
- // FreeMem( cmdbuf, strlen( ARG0(rexxmsg)+1 ) );
- */
- FreeMem( (void *)cmdbuf, memsize );
- /* ACRM- */
-
- /* Look at macro loopback */
-
- if( ( rexxmsg->rm_Result1 == RXERR_UNKNOWN_CMD ) &&
- FlagIsClear( global_rdef->Flags, RXIL_NOLAUNCH ) )
- {
- /* Unknown command. Try to launch it as an ARexx macro. */
- child_rxi = RxilCreateRxi( ARG0(rexxmsg), RXCOMM );
-
- if( child_rxi != NULL )
- {
- if( FlagIsSet( rexxmsg->rm_Action, RXFF_RESULT ) )
- {
- SetFlag( child_rxi->ActionFlags, RXFF_RESULT );
- }
-
- child_rxi->Parent = rexxmsg;
-
- if( RxilLaunch( child_rxi ) == 0 )
- {
- /* Launched successfully */
- return; /* Return without replying */
- }
- else
- {
- /* Launch failure */
- RxilDeleteRxi( child_rxi );
- rexxmsg->rm_Result1 = RXERR_FAILED;
- }
- }
- else
- {
- /* Unable to create RxilInvocation structure */
- rexxmsg->rm_Result1 = RXERR_NO_MEMORY;
- }
- }
-
-
- RxilCheckResult( rexxmsg );
-
- ReplyMsg( (struct Message *)rexxmsg );
- }
-
-
-
- static void handle_return( struct RxilInvocation *rxi )
- {
- rxi->State = RXIL_STATE_RETURNED;
-
- if( rxi->CommAddr == global_rdef->SecretPortName )
- {
- /* This implies that the locked flag was set while
- * this ran. Decrement the lock count.
- */
- --(global_rdef->LockCount);
- }
-
-
- if( rxi->Parent == NULL )
- {
- /* This was originated by the client. Let the client
- * worry about handling the return and doing the cleanup.
- */
- return;
- }
-
-
- /* This is the return for a program which was "looped" back out
- * to ARexx.
- */
-
- /* Pass thru?? the result */
-
- rxi->Parent->rm_Result1 = rxi->RexxMsg->rm_Result1;
- rxi->Parent->rm_Result2 = rxi->RexxMsg->rm_Result2;
-
- RxilCheckResult( rxi->Parent );
-
-
- /* Reply to the parent */
- ReplyMsg( (struct Message *)(rxi->Parent) );
-
-
- /* Cleanup the invocation RexxMsg */
-
- /* Zero these to prevent the cleanup routine from freeing
- * the return Argstring.
- */
- rxi->RexxMsg->rm_Result1 = 0;
- rxi->RexxMsg->rm_Result2 = 0;
-
- /* Clear these to prevent the cleanup routine from closing
- * streams which were inherited from the parent.
- */
- rxi->RexxMsg->rm_Stdin = NULL;
- rxi->RexxMsg->rm_Stdout = NULL;
-
- RxilCleanupReturn( rxi );
-
-
- /* And free the RxilInvocation structure */
- RxilDeleteRxi( rxi );
- }
-
-
-
- /* This is intended to be a very memory efficient parsing procedure.
- * The length of the options is limited only by the length of the
- * input line buffer (owned by the caller). The number of arguments which
- * can be parsed out of an input string is limited by the size of the
- * pointer array, which is also owned by the caller.
- * Note that this WILL MODIFY the contents of the line passed in the
- * buffer. If this is un-desirable, copy the string to a scratch buffer
- * and pass that.
- *
- * The calling should look something like:
- * char *myargpointers[10];
- * int myargcount;
- * char buf[100];
- *
- * gets( buf );
- * myargcount = inplace_parse( buf, myargpointers, 10 );
- */
-
- static int parse_inplace( char *p, char **argptr, int maxargs )
- {
- BOOL inparen = FALSE, inarg = FALSE;
- char *argstart = 0; /* Does not really need to be initialized */
- int argcount = 0;
-
-
- while( (*p != '\0') && (argcount < maxargs) )
- {
- switch( *p )
- {
- case ' ':
- case '\t':
- /* Whitespace */
- if( (inarg == TRUE) && (inparen == FALSE) )
- {
- /* We got one! */
- *p = '\0'; /* place a delimiting null */
- argptr[argcount++] = argstart;
- inarg = FALSE;
- inparen = FALSE;
- }
- break;
-
- case '"':
- if( inparen == TRUE )
- {
- /* This is closing paren */
- /* We got one! */
- *p = '\0'; /* place a delimiting null */
- argptr[argcount++] = argstart;
- inarg = FALSE;
- inparen = FALSE;
- }
- else
- {
- /* Opening paren */
- if( inarg == TRUE )
- {
- /* Deal with the previous arg first */
- *p = '\0'; /* place a delimiting null */
- argptr[argcount++] = argstart;
- }
-
- inparen = TRUE;
- inarg = TRUE;
- argstart = p+1;
- }
- break;
-
- default:
- /* A character we want in an argument string */
- if( inarg == FALSE )
- {
- inarg = TRUE;
- argstart = p;
- }
- break;
- }
-
- p++;
- }
-
- if( (inarg == TRUE) && (argcount < maxargs) )
- argptr[argcount++] = argstart;
-
- return( argcount );
- }
-
-